﻿using System;
using System.Linq;
using System.IO;
using System.IO.IsolatedStorage;
using System.Collections.Generic;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Framework.Client;
using Microsoft.LightSwitch.Presentation;
using Microsoft.LightSwitch.Presentation.Extensions;
using System.Windows.Controls;
using System.ServiceModel.DomainServices.Client;


namespace LightSwitchApplication
{
    /// <summary>
    /// Enum stato avanzamento.
    /// Deve coincidere con Choice List
    /// </summary>
    public enum StatoAvanzamento
    {
        MaterialeOrdinato,
        TagliatoInCoda,
        InCoda,
        InTrattamento,
        DaConsegnare,
        Consegnato,
        MaterialeDaTagliare,
    }

    public partial class PRO_OrdiniCliente
    {
        partial void DettagliDocumento_Changed(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
            {
                // Su nuovo aggiunto devo salvare numero di riga
                var documento = OrdiniCliente.SelectedItem;

                var max = 0;

                foreach (var d in documento.DettagliDocumento)
                    if (d.NumeroRiga.HasValue && d.NumeroRiga.Value > max)
                        max = d.NumeroRiga.Value;

                var nItems = e.NewItems.OfType<DettaglioDocumento>();

                foreach (var ni in nItems)
                {
                    max++;
                    ni.NumeroRiga = max;

                    // Setto stato avanzamento
                    if (documento.TipoDocumento == (int)TipoDocumento.OrdineCliente)
                        ni.StatoAvanzamento = (int)StatoAvanzamento.InCoda;
                }


            }
        }

        partial void DocumentoArchiviato_Changed()
        {
        }
        #region New Order Detail
        const string ModalWindow = "NewDetailDialog";

        partial void DettagliDocumentoAddAndEditNew_CanExecute(ref bool result)
        {
            // Write your code here.
        }

        partial void DettagliDocumentoAddAndEditNew_Execute()
        {
            // Write your code here.
            var newDett = this.DataWorkspace.ApplicationData.DettagliDocumento.AddNew();
            newDett.Documento = OrdiniCliente.SelectedItem;
            DettagliDocumento.SelectedItem = newDett;

            this.OpenModalWindow(ModalWindow);

            this.FindControl(ModalWindow).ControlAvailable += new EventHandler<ControlAvailableEventArgs>(NewSubscriber_WindowAvailable);
        }
        partial void DettagliDocumentoEditSelected_CanExecute(ref bool result)
        {
        }

        partial void DettagliDocumentoEditSelected_Execute()
        {
            this.OpenModalWindow(ModalWindow);

            this.FindControl(ModalWindow).ControlAvailable += new EventHandler<ControlAvailableEventArgs>(NewSubscriber_WindowAvailable);
        }
        #endregion

        void NewSubscriber_WindowAvailable(object sender, ControlAvailableEventArgs e)
        {
            this.FindControl(ModalWindow).ControlAvailable -= new EventHandler<ControlAvailableEventArgs>(NewSubscriber_WindowAvailable);

            ((ChildWindow)e.Control).MinWidth = 260;

            ((ChildWindow)e.Control).Closed += new EventHandler(DocumentiListDetail_Closed);

            ((ChildWindow)e.Control).Closing += new EventHandler<System.ComponentModel.CancelEventArgs>(OrdiniCliente_MasterDetail_Closing);

            this.FindControl("MwArticolo").ControlAvailable += new EventHandler<ControlAvailableEventArgs>(DocumentiListDetail_ControlAvailable);
        }

        void OrdiniCliente_MasterDetail_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (DettagliDocumento.SelectedItem.Articolo == null)
            {
                e.Cancel = true;
            }
        }

        AutoCompleteBox ac;
        void DocumentiListDetail_Closed(object sender, EventArgs e)
        {
            ((ChildWindow)sender).MinWidth = 0;

            this.FindControl("MwArticolo").ControlAvailable -= new EventHandler<ControlAvailableEventArgs>(DocumentiListDetail_ControlAvailable);

            if (ac != null)
                ac.LostFocus -= ac_LostFocus;

            ac = null;
        }

        void DocumentiListDetail_ControlAvailable(object sender, ControlAvailableEventArgs e)
        {
            ac = e.Control as AutoCompleteBox;
            if (ac != null)
                ac.LostFocus += new System.Windows.RoutedEventHandler(ac_LostFocus);
        }

        void ac_LostFocus(object sender, System.Windows.RoutedEventArgs e)
        {
            string txtComboText = ((System.Windows.Controls.AutoCompleteBox)sender).Text;

            this.Details.Dispatcher.BeginInvoke(() =>
            {
                if (!string.IsNullOrEmpty(txtComboText))
                {
                    var selectedCategory = this.DataWorkspace.ApplicationData.Articoli.Where(A => A.CodiceArticolo == txtComboText).FirstOrDefault();

                    if (selectedCategory == null)
                    {
                        //Category doesn't exists
                        if (this.ShowMessageBox("Vuoi aggiungere articolo codice " + txtComboText + " ?", "Aggiungi Articolo", MessageBoxOption.YesNo) == System.Windows.MessageBoxResult.Yes)
                        {
                            selectedCategory = this.DataWorkspace.ApplicationData.Articoli.AddNew();
                            selectedCategory.CodiceArticolo = txtComboText;
                            this.DataWorkspace.ApplicationData.SaveChanges();

                            this.DettagliDocumento.SelectedItem.Articolo = selectedCategory;
                        }
                    }
                }
            });
        }

        /// <summary>
        /// Mostra dettagli ordine
        /// </summary>
        partial void ShowDettagliOrdine_Execute()
        {
            this.Application.ShowPRO_CodaProduzione(OrdiniCliente.SelectedItem.Id);
        }

        /// <summary>
        /// Mostra dettagli materiale per ordine.
        /// </summary>
        partial void ShowRiepilogoMaterialeOrdine_Execute()
        {

            var riepScreen = this.Application.ActiveScreens.Where(s => s.GetName() == "RMA_RiepilogoMaterialeOrdine").FirstOrDefault();
            if (riepScreen != null)
                riepScreen.Close(false);

            // Crea dettagli materiale.
            var success = CreateDettagliMaterialeRecord();

            if (success)
            {
                // Mostra schermata.
                this.Application.ShowRMA_RiepilogoMaterialeOrdine(OrdiniCliente.SelectedItem.Id);
            }
        }

        /// <summary>
        /// Crea riepilogo materiale 
        /// </summary>
        /// <returns></returns>
        private bool CreateDettagliMaterialeRecord()
        {
            //Chiudo finestra aperta di riepilogo ordine , se aperta.


            //DataWorkspace.ApplicationData.SaveChanges();

            var ordineId = OrdiniCliente.SelectedItem.Id;

            var ordineCliente = DataWorkspace.ApplicationData.Documenti_Single(ordineId);

            if (ordineCliente == null) return false;

            // Cancello dettagli precedenti

            foreach (RiepilogoMateriale m in DataWorkspace.ApplicationData.RiepilogoMateriali.Where(d => d.Documento.Id == ordineCliente.Id))
                m.Delete();

            Save();

            //foreach (var r in ordineCliente.RiepilogoMateriali)
            //    r.Ordinare = false;

            /*
             * Raccolgo materiale.
             */

            // Save();

            var dettDoc = ordineCliente.DettagliDocumento;

            foreach (var dettaglioDocumento in dettDoc)
            {
                var art = dettaglioDocumento.Articolo;
                if (art == null) continue;

                foreach (var dettaglioMaterialeArticolo in art.DettagliMaterialeArticolo)
                {
                    var materiale = dettaglioMaterialeArticolo.MaterialeGrezzo;

                    /*
                     * Se deve essere tagliato da fornitore inserisco una voce a parte.
                     * Altrimenti cerco voce con stesso id materiale e incremento quantita.
                     */
                    if (dettaglioMaterialeArticolo.TaglioFornitore)
                    {
                        var rF = ordineCliente.RiepilogoMateriali.AddNew();

                        rF.MaterialeGrezzo = materiale;
                        rF.Ordinare = false;
                        rF.NumeroPezzi = dettaglioDocumento.Quantità;
                        rF.LunghezzaTaglio = dettaglioMaterialeArticolo.LunghezzaPezzo;
                        rF.Totale = dettaglioDocumento.Quantità * dettaglioMaterialeArticolo.LunghezzaPezzo;
                        rF.TaglioInMisura = true;
                        rF.Impegnato = GetMaterialeImpegnato(materiale.Id);

                        rF.InOrdine = GetMaterialeInOrdine(materiale.Id);
                    }

                    else // Acquisto barra intera.
                    {
                        var qtaDaAggiungere = dettaglioDocumento.Quantità *
                                              dettaglioMaterialeArticolo.LunghezzaPezzo;


                        // todo : aggiungere tagliato da fornitore.

                        var riepilogoMateriale = ordineCliente.RiepilogoMateriali;

                        var voceEsistente = riepilogoMateriale.Where(v => v.MaterialeGrezzo.Id == dettaglioMaterialeArticolo.MaterialeGrezzo.Id && !v.TaglioInMisura).FirstOrDefault();

                        if (voceEsistente != null)
                        {
                            if (!voceEsistente.Totale.HasValue)
                                voceEsistente.Totale = 0;

                            voceEsistente.Totale += qtaDaAggiungere;

                            voceEsistente.Impegnato = GetMaterialeImpegnato(materiale.Id);

                            voceEsistente.InOrdine = GetMaterialeInOrdine(materiale.Id);

                        }
                        else
                        {
                            var r = ordineCliente.RiepilogoMateriali.AddNew();
                            r.MaterialeGrezzo = materiale;

                            if (!r.Totale.HasValue)
                                r.Totale = 0;

                            r.Totale += qtaDaAggiungere;

                            r.Impegnato = GetMaterialeImpegnato(materiale.Id);

                            r.InOrdine = GetMaterialeInOrdine(materiale.Id);
                        }
                    }
                }
            }

            Save();


            // Ora creo i dettagli del riepilogo.
            // Collego i vari dettagli documento con i riepiloghi

            var riepMateriale = ordineCliente.RiepilogoMateriali;

            foreach (var rm in riepMateriale)
            {
                foreach (var dt in dettDoc)
                {
                    var art = dt.Articolo;
                    if (art == null) continue;

                    foreach (var dettaglioMaterialeArticolo in art.DettagliMaterialeArticolo)
                    {
                        var materiale = dettaglioMaterialeArticolo.MaterialeGrezzo;

                        if (rm.MaterialeGrezzo.Id == materiale.Id)
                        {
                            var dettRm = rm.DettaglioRiepilogoMateriali.AddNew();

                            dettRm.DettaglioDocumento = dt;
                            dettRm.DettaglioMaterialeArticolo = dettaglioMaterialeArticolo;
                        }
                    }
                }
            }

            Save();

            return true;
        }

        /// <summary>
        /// Somma il materiale in ordine
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        private decimal? GetMaterialeInOrdine(int p)
        {
            var ordini = DataWorkspace.ApplicationData.Documenti.Where(d => d.TipoDocumento == (int)TipoDocumento.OrdiniFornitoreMateriale && (!d.Emesso || !d.Archiviato));

            var result = 0.0m;

            foreach (Documento o in ordini)
            {
                foreach (var dd in o.DettagliDocumentoMateriale)
                {
                    if (dd.MaterialeGrezzo.Id != p) continue;

                    if (dd.TaglioInMisura && dd.NumeroPezzi.HasValue && dd.LunghezzaTaglio.HasValue)
                        result += dd.NumeroPezzi.Value * dd.LunghezzaTaglio.Value;
                    else if (dd.Totale.HasValue)
                        result += dd.Totale.Value;
                }
            }

            return result;

        }

        /// <summary>
        /// Somma il materiale impegnato
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        private decimal GetMaterialeImpegnato(int materialeId)
        {
            var dettagli = DataWorkspace.ApplicationData.DettagliDocumento.Where(d => d.Documento.Archiviato == false && d.Documento.TipoDocumento == (int)TipoDocumento.OrdineCliente && (d.StatoAvanzamento == (int)StatoAvanzamento.InCoda || d.StatoAvanzamento == (int)StatoAvanzamento.MaterialeOrdinato));

            var result = 0.0m;

            foreach (DettaglioDocumento d in dettagli)
            {
                if (d.Articolo == null) continue;

                foreach (var dm in d.Articolo.DettagliMaterialeArticolo)
                {
                    if (dm.MaterialeGrezzo.Id == materialeId)
                    {
                        result += dm.LunghezzaPezzo * d.Quantità;
                    }
                }
            }

            return result;
        }

        partial void DocumentoListAddAndEditNew_CanExecute(ref bool result)
        {
            // Write your code here.

        }

        const string NewCustomerOrder = "NewOrderDialog";


        /// <summary>
        /// Nuovo ordine.
        /// </summary>
        partial void DocumentoListAddAndEditNew_Execute()
        {
            // Write your code here.
            var newDett = this.DataWorkspace.ApplicationData.Documenti.AddNew();

            OrdiniCliente.SelectedItem = newDett;

            newDett.Data = DateTime.Now;

            // Dichiara tipo documento 
            if (DocumentoTipoDocumento == null || !DocumentoTipoDocumento.HasValue || DocumentoTipoDocumento.Value == (int)TipoDocumento.OrdineCliente)
                newDett.TipoDocumento = (int)TipoDocumento.OrdineCliente;
            else
                newDett.TipoDocumento = (int)TipoDocumento.PreventivoCliente;

            this.OpenModalWindow(NewCustomerOrder);
        }

        /// <summary>
        /// Edita ordine override
        /// </summary>
        /// <param name="result"></param>
        partial void DocumentoListEditSelected_CanExecute(ref bool result)
        {
        }

        partial void DocumentoListEditSelected_Execute()
        {
            this.OpenModalWindow(NewCustomerOrder);
        }

        partial void ShowPreventivi_Execute()
        {
            DocumentoTipoDocumento = (int)TipoDocumento.PreventivoCliente;
            DocumentoArchiviato = false;
        }

        partial void PRO_OrdiniCliente_InitializeDataWorkspace(List<IDataService> saveChangesTo)
        {
            DocumentoTipoDocumento = (int)TipoDocumento.OrdineCliente;
            DocumentoArchiviato = false;
        }

        partial void ShowSoloOrdini_Execute()
        {
            DocumentoTipoDocumento = (int)TipoDocumento.OrdineCliente;
            DocumentoArchiviato = false;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="handled"></param>
        partial void PRO_OrdiniCliente_Saving(ref bool handled)
        {
            handled = true;
            try
            {
                this.DataWorkspace.ApplicationData.SaveChanges();
            }
            catch (ConcurrencyException ex)
            {
                foreach (IEntityObject conflict in ex.EntitiesWithConflicts)
                {
                    if (conflict.Details.EntityConflict.IsDeletedOnServer)
                    {
                        conflict.Details.EntityConflict.ResolveConflicts
                         (Microsoft.LightSwitch.Details.ConflictResolution.ServerWins);
                    }
                    else
                    {
                        conflict.Details.EntityConflict.ResolveConflicts
                         (Microsoft.LightSwitch.Details.ConflictResolution.ClientWins);
                    }
                }
            }

            //    foreach (IEntityObject entityConflict in e.EntitiesWithConflicts)
            //    {
            //        if (entityConflict is RiepilogoMateriale)
            //        {
            //            //entityConflict.Details.DiscardChanges();



            //            entityConflict.Details.EntityConflict.ResolveConflicts(Microsoft.LightSwitch.Details.ConflictResolution.ClientWins);
            //            //entityConflict.Delete();
            //        }

            //        //EntityPropertyConflict statusProperty =
            //        //   entityConflict.Details.EntityConflict.ConflictingProperties.Where(
            //        //   property => property.Property.Name == "Status").Single();
            //        //if (statusProperty.Property.Value.ToString() == statusProperty.ServerValue.ToString())
            //        //{
            //        //    statusProperty.EntityConflict.ResolveConflicts(ConflictResolution.ClientWins);
            //        //    //Resave once we’ve resolved the conflicts
            //        //    this.DataWorkspace.ApplicationData.SaveChanges();
            //        //}
            //    }
            //    try
            //    {

            //        this.DataWorkspace.ApplicationData.SaveChanges();
            //    }
            //    catch (Exception ex)
            //    {
            //        handled = false;
            //    }
            //    finally
            //    {
            //        handled = false;
            //    }
            //}
            //catch (Exception ex)
            //{
            //    handled = false;
            //}
            //finally
            //{
            //    handled = false;
            //}

        }







    }
}

